//
//  XPPAutoCompleteHelper.m
//  XPPXcodePlugin
//
//  Created by yoyokko on 10-9-5.
//  Copyright 2010 yoyokko@gmail.com. All rights reserved.
//

#import "XPPAutoCompleteHelper.h"
#import "XPPClassName.h"
#import "XPPXcodePlugin.h"
#import "PBXExtendedOutlineView.h"
#import "PBXFileReference.h"
#import "PBXSmartGroupTreeModule.h"
#import "PBXGroup.h"
#import "NSStringAddition.h"


static XPPAutoCompleteHelper *sharedInstance = nil; 

@implementation XPPAutoCompleteHelper


@synthesize prefixAndTextDictionary = prefixAndTextDictionary_;
@synthesize prefixAndCousorDictionary = prefixAndCousorDictionary_;
@synthesize projectGroupOutlineView = projectGroupOutlineView_;

+ (void) initialize
{
    if (sharedInstance == nil)
        sharedInstance = [[self alloc] init];
}

+ (id) sharedXPPAutoCompleteHelper
{
    //Already set by +initialize.
    return sharedInstance;
}

+ (id) allocWithZone:(NSZone*)zone
{
    //Usually already set by +initialize.
    @synchronized(self) {
        if (sharedInstance) {
            //The caller expects to receive a new object, so implicitly retain it
            //to balance out the eventual release message.
            return [sharedInstance retain];
        } else {
            //When not already set, +initialize is our caller.
            //It's creating the shared instance, let this go through.
            return [super allocWithZone:zone];
        }
    }
	return nil;
}

- (id) init
{
    //If sharedInstance is nil, +initialize is our caller, so initialize the instance.
    //If it is not nil, simply return the instance without re-initializing it.
    if (sharedInstance == nil) {
		self = [super init];
		if (self) {
            self.prefixAndTextDictionary = [NSMutableDictionary dictionary];
			self.prefixAndCousorDictionary = [NSMutableDictionary dictionary];
			[self loadXcodeKeyTextFile];
			[self fun];
			self.projectGroupOutlineView = [self getTheProjectGroupsOutlineView:[[[NSApplication sharedApplication] mainWindow] contentView]];
        }
    }
    return self;
}

- (id) copyWithZone:(NSZone*)zone
{
    return self;
}

- (id) retain
{
    return self;
}

- (unsigned) retainCount
{
    return UINT_MAX; // denotes an object that cannot be released
}

- (void) release
{
    // do nothing 
}

- (id) autorelease
{
    return self;
}

- (void) dealloc
{
	self.prefixAndCousorDictionary = nil;
	self.prefixAndTextDictionary = nil;
	self.projectGroupOutlineView = nil;
	
	[super dealloc];
}

- (void) loadXcodeKeyTextFile
{
	NSString *plistFilePath = [@"/Library/Application Support/XPP/xcodekeytext.plist" stringByStandardizingPath];
	//	NSString *plistFilePath = [[XPPXcodePlugin pluginBundle] pathForResource:@"xcodekeytext" 
	//																	  ofType:@"plist"];
	if (![[NSFileManager defaultManager] fileExistsAtPath:plistFilePath])
	{
		NSLog(@"xcodekeytext.plist is not exists.");
	}else
	{
		[self processXCodeKeyTextDictionary:[NSDictionary dictionaryWithContentsOfFile:plistFilePath]];
	}
}

- (void) fun
{
	NSLog(@"Fun enough? YES.");
}

- (NSString *) textForPrefix:(NSString *) prefix
{
	if (!prefix)
		return nil;
	if (![prefix isKindOfClass:[NSString class]])
		return nil;
	if ([prefix isEqualToString:@""])
		return nil;
	
	return [self.prefixAndTextDictionary objectForKey:prefix];
}

- (int) cousorIndexForPrefix:(NSString *) prefix
{
	if (!prefix)
		return -1;
	if (![prefix isKindOfClass:[NSString class]])
		return -1;
	if ([prefix isEqualToString:@""])
		return -1;
	NSNumber *index = [self.prefixAndCousorDictionary objectForKey:prefix];
	if (index) {
		return [index intValue];
	}
	return -1;
}

- (void) addPrefix:(NSString *) prefix andText:(NSString *) text
{
	if(!prefix || !text)
		return;
	[self.prefixAndTextDictionary setObject:text forKey:prefix];
}

- (void) addPrefix:(NSString *) prefix andCursorIndex:(NSNumber *) cursorIndex
{
	if(!prefix || !cursorIndex)
		return;
	[self.prefixAndCousorDictionary setObject:cursorIndex forKey:prefix];
}

- (void) processXCodeKeyTextDictionary:(NSDictionary *)keyTextDict
{
	// check that the incoming dict is not nil or is kind of NSDictionary.
	if(!keyTextDict || ![keyTextDict isKindOfClass:[NSDictionary class]])
	{
		return;
	}
	
	NSArray *allKeys = [keyTextDict allKeys];
	int index, count = [allKeys count];
	for(index = 0; index < count; index ++)
	{
		// key name is prefix name.
		NSString *curKey = [allKeys objectAtIndex:index];
		NSDictionary *temp = (NSDictionary *)[keyTextDict objectForKey:curKey];
		if(temp)
		{
			NSString *text			= [temp objectForKey:@"text"];
			NSNumber *cursor		= [temp objectForKey:@"cursor"];
			
			// we add completekey, text and cursor into our map dictionary.
			[self addPrefix:curKey andText:text];
			[self addPrefix:curKey andCursorIndex:cursor];
		}
	}
}

- (PBXExtendedOutlineView *) theProjectGroupOutlineView
{
	if (!self.projectGroupOutlineView) {
		self.projectGroupOutlineView = [self getTheProjectGroupsOutlineView:[[[NSApplication sharedApplication] mainWindow] contentView]];
	}
	return self.projectGroupOutlineView;
}

- (PBXExtendedOutlineView *) getTheProjectGroupsOutlineView:(NSView *) rootView
{
	if ([rootView isKindOfClass:[PBXExtendedOutlineView class]]) {
		return (PBXExtendedOutlineView *)rootView;
	}
	for (NSView *view in [rootView subviews])
	{
		if ([view isKindOfClass:[PBXExtendedOutlineView class]]) {
			return (PBXExtendedOutlineView *)view;
		}else {
			return [self getTheProjectGroupsOutlineView:view];
		}
	}
	return nil;
}

- (PBXGroup *) rootGroupOfContext
{
	PBXExtendedOutlineView *outlineView = [self theProjectGroupOutlineView];
	PBXSmartGroupTreeModule *datasource = (PBXSmartGroupTreeModule *)[outlineView dataSource];
	PBXGroup *rootGroupOfContext = [datasource rootGroupOfContext];
	return rootGroupOfContext;
}

- (PBXFileReference *) implementationFileForFileName:(NSString *) headerFileName 
								  inRootGroupContext:(PBXGroup *) rootGroupContext
{
	if ([headerFileName length] == 0)
	{
		return nil;
	}
	if ([[rootGroupContext fileType] isSourceCode] && [[rootGroupContext name] hasPrefix:headerFileName])
	{
		return rootGroupContext;
	}
	
	for (PBXGroup *oneGroup in [rootGroupContext children]) 
	{
		if ([oneGroup isGroup]) 
		{
			PBXFileReference *temp = [self implementationFileForFileName:headerFileName inRootGroupContext:oneGroup];
			if (temp) {
				return temp;
			}
		}
		else if ([[oneGroup fileType] isSourceCode] && [[oneGroup name] hasPrefix:headerFileName])
		{
			return oneGroup;
		}
	}
	return nil;
}
/*
- (BOOL) isVariableHasProperty:(NSString *) variableName 
					 className:(NSString *) className
					   forFile:(NSString *) headerFileName
{
	if ([variableName length] == 0 || [className length] == 0 || [headerFileName length] == 0) {
		return NO;
	}
	headerFileName = [headerFileName stringByReplacingOccurrencesOfString:@".h" withString:@""];
	headerFileName = [headerFileName stringByAppendingString:@".m"];
	PBXFileReference *implementationFile = [self implementationFileForFileName:headerFileName
															inRootGroupContext:[self rootGroupOfContext]];
	if (implementationFile) {
		NSString *implementString = [NSString stringWithContentsOfFile:[implementationFile resolvedAbsolutePath]];
		NSArray *seperatedStrings = [implementString componentsSeparatedByString:@"@implementation"];
		if ([seperatedStrings count] >= 2) 
		{
			for (int index = 1; index < [seperatedStrings count]; index++)
			{
				NSString *trimedString = [[seperatedStrings objectAtIndex:index] 
										  stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
				if ([trimedString hasPrefix:className])
				{
					// find the implementation section of className
					NSArray *allSynthesize = [trimedString componentsSeparatedByString:@"@synthesize"];
					if ([allSynthesize count] >= 2)
					{
						for (int i = 1; i < [allSynthesize count]; i++)
						{
							NSString *oneSynthesize = [[allSynthesize objectAtIndex:i] 
													   stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
							// @synthesize propery;
							if ([oneSynthesize isEqualToString:variableName]) {
								return YES;
							}
							// @synthese propery=propery_;
							NSRange range = [oneSynthesize rangeOfString:variableName];
							if (range.location != NSNotFound) 
							{
								// we found the variable? check again
								unsigned char beforeOne = [oneSynthesize characterAtIndex:range.location-1];
								unsigned char afterOne = [oneSynthesize characterAtIndex:range.length+range.location];
								if ((beforeOne == ' ' || beforeOne == '=') &&
									(afterOne == ' ' || afterOne == ';'))
								{
									return YES;
								}
							}
						}
					}
				}
			}
		}
	}
	return NO;
}
 
 */



- (NSRange)rangeOfClassName:(NSString*)className
					 inFile:(PBXFileReference*)fileReference{
	NSTextStorage *text = [[[fileReference bookmark] fileDocumentLoadIfNeeded:YES] textStorage];
	
//	NSString *headerSourceCode = [NSString stringWithContentsOfFile:[fileReference resolvedAbsolutePath]];
	NSString *headerSourceCode = [text string];
	
	NSArray *temp = [headerSourceCode componentsSeparatedByString:@"@interface"];
	NSString *classString = nil;
	for(NSString *string in temp){
		NSRange range = [string rangeOfString:@":"];
		if (NSNotFound != range.location ) {
			NSString *tempClassName = [[string substringToIndex:range.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
			if ([tempClassName isEqualToString:className]) {
				classString = string;
				break;
			}
		}
	}
	if (nil == classString || [classString length] == 0) {
		return NSMakeRange(NSNotFound, 0);
	}else {
		return [headerSourceCode rangeOfString:classString];
	}

}

- (NSMutableArray *)allPropertyForClass:(NSString*)className
								forFile:(PBXFileReference*)fileReference{

//	NSString *headerSourceCode = [NSString stringWithContentsOfFile:[fileReference resolvedAbsolutePath]];
	NSTextStorage *text = [[[fileReference bookmark]fileDocumentLoadIfNeeded:YES] textStorage];
	NSString *headerSourceCode = [text string];
	NSArray *temp = [headerSourceCode componentsSeparatedByString:@"@interface"];
	NSString *classString = nil;
	for(NSString *string in temp){
		NSRange range = [string rangeOfString:@":"];
		if (NSNotFound != range.location ) {
			NSString *tempClassName = [[string substringToIndex:range.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
			if ([tempClassName isEqualToString:className]) {
				classString = string;
				break;
			}
		}
	}
	if (nil == classString || [classString length] == 0) {
		return nil;
	}
	
	NSString *tempString = [classString subStringSourceBetweenStringStart:@"}"
																	  end:@"@end"];
	NSArray *tempArray = [tempString componentsSeparatedByString:@"\n"];
	NSMutableArray *propertyArray = [NSMutableArray array];
	for(NSString *line in tempArray){
		if ([line hasPrefix:@"@property"] ) {
			[propertyArray addObject:line];
		}
	}
	
	return propertyArray;
}

- (BOOL)isArrayContainString:(NSArray*)array string:(NSString*)string{

	for(NSString * line in array){
		if ([line isKindOfClass:[NSString class]]) {
			NSRange range = [line rangeOfString:string];
			if (NSNotFound != range.location) {
				return YES;
			}
		}
	}
	return NO;
}

- (NSString*)lineThatContainString:(NSString*)string inArray:(NSArray*)array{
	if (nil == array || [array count] == 0) {
		return nil;
	}
	for(NSString *line in array){
		if ([line isKindOfClass:[NSString class]]) {
			if ([line isStringContainOtherString:string]) {
				NSArray *temp = [line componentsSeparatedByString:@"\t"];
				for(NSString *part in temp){
					
					part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
					part = [part stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"*"]];
					part = [part stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@";"]];
					if ([part isEqualToString:string]) {
						return line;
					}
					
				}

				temp = [line componentsSeparatedByString:@" "];
				for(NSString *part in temp){
					
					part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
					part = [part stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"*"]];
					part = [part stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@";"]];
					if ([part isEqualToString:string]) {
						return line;
					}
					
				}				
			}
		}
	}
	return nil;
}
- (NSMutableArray *)allSynthesizeForClass:(NSString*)className 
								  forFile:(NSString*)headerFileName
{
	if ([className length] == 0 || [headerFileName length] == 0) {
		return nil;
	}
	headerFileName = [headerFileName stringByReplacingOccurrencesOfString:@".h"
															   withString:@".m"];
	PBXFileReference *implementationFile = [self implementationFileForFileName:headerFileName
															inRootGroupContext:[self rootGroupOfContext]];
	NSMutableArray *resultArray = [NSMutableArray array];
	if (implementationFile) {
//		NSString *implementString = [NSString stringWithContentsOfFile:[implementationFile resolvedAbsolutePath]];
		NSTextStorage *text = [[[implementationFile bookmark]fileDocumentLoadIfNeeded:YES] textStorage];
		NSString *implementString = [text string];

		implementString = [implementString removeAllComments];
		
		NSArray *seperatedStrings = [implementString componentsSeparatedByString:@"@implementation"];
		if ([seperatedStrings count] >= 2) 
		{
			for (int index = 1; index < [seperatedStrings count]; index++)
			{
				
				NSString *trimedString = [[seperatedStrings objectAtIndex:index] 
										  stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
				if ([trimedString hasPrefix:className])
				{
					// find the implementation section of className
					//					NSArray *allSynthesize = [trimedString componentsSeparatedByString:@"@synthesize"];
//					NSArray *allSynthesize = [self getAllTheStringBetweenStartWith:@"@synthesize"
//																		   endWith:@";"
					NSArray *allSynthesize = [trimedString getAllTheStringBetweenStartWith:@"synthesize"
																				   endWith:@";"];

//					NSLog(@"allSynthesize = %@",allSynthesize);
					if (allSynthesize != nil && [allSynthesize count] > 0)
					{
						for (NSString *line in allSynthesize)
						{
							
							line = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
							NSArray *synthesizes = [line componentsSeparatedByString:@","];
							for(NSString *item in synthesizes)
							{
								NSArray *arrayB = [item componentsSeparatedByString:@"="];
								for(NSString * string in arrayB)
								{
									string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
									[resultArray addObject:string];
//									NSLog(@"%@",string);
								}
								
							}
						}
					}
				}
			}
		}
	}
	return [resultArray count] > 0 ? resultArray : nil;
	
}

- (NSArray *) classNamesInSourceFile:(PBXFileReference *) fileReference
{
	if (!fileReference){
		return nil;
	}
	NSFileManager *fileManager = [NSFileManager defaultManager];
	if ([fileManager fileExistsAtPath:[fileReference resolvedAbsolutePath]])
	{
//		NSString *sourceCode = [NSString stringWithContentsOfFile:[fileReference resolvedAbsolutePath]];
		NSString *sourceCode = [[[[fileReference bookmark] fileDocumentLoadIfNeeded:YES] textStorage] string];
		sourceCode = [sourceCode removeAllComments];
		NSArray *seperatedStrings = [sourceCode componentsSeparatedByString:@"@interface"];
		// ignor the first object of array
		if ([seperatedStrings count] >= 2)
		{
			NSMutableArray *allClasses = [NSMutableArray array];
			// we have at least one class definitions, and it starts with second object
			for (int index = 1; index < [seperatedStrings count]; index++) 
			{
				NSString *classString = [seperatedStrings objectAtIndex:index];
				NSRange range = [classString rangeOfString:@":"];
				if (range.location != NSNotFound)
				{
					// find the class name
					NSString *className = [[classString substringToIndex:range.location] 
										   stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//					className = [className removeAllComments];
					
					NSMutableArray *synthesizeArray = [self allSynthesizeForClass:className
																		  forFile:[fileReference name]];
					NSLog(@"synthesize Array = %@",synthesizeArray);
					// find the left { of the interface
					NSRange rangeOfLeft = [classString rangeOfString:@"{"];
					// find the right { of the interface
					NSRange rangeOfRight = [classString rangeOfString:@"}"];
					NSMutableArray *oneVariableArray = [NSMutableArray array];
					// check whether we found it
					if (rangeOfLeft.location != NSNotFound && rangeOfRight.location != NSNotFound)
					{
						NSString *variableString = [classString substringWithRange:NSMakeRange(rangeOfLeft.location+1, rangeOfRight.location-rangeOfLeft.location-1)];
						NSArray *sepratedVariables = [variableString componentsSeparatedByString:@";"];
						
						NSMutableArray *propertyArray = [NSMutableArray array];
						
						//collect @property strings 
						NSArray * lineArray = [classString componentsSeparatedByString:@"\n"];
						for(NSString *line in lineArray){
							if ([line hasPrefix:@"@property"]) {
								[propertyArray addObject:line];
							}
						}
						// get all variable definitions
						for (NSString *oneVariable in sepratedVariables) 
						{
							NSString *trimVariable = [oneVariable stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
							// it is not a comment line and not a blank line.
							if ([trimVariable length] != 0) 
							{
								// check whether it is a point value
								NSRange rangeOfPoint = [trimVariable rangeOfString:@"*"];
								XPPVariable *variable = [[XPPVariable alloc] init];

								NSString *propertyString = nil;
								for(NSString *line in propertyArray){
									NSRange range = [line rangeOfString:trimVariable];
									if (NSNotFound != range.location) {
										propertyString = line;
										break;
									}
								}
								NSString *propertyType = [propertyString subStringSourceBetweenStringStart:@"("
																									   end:@")"];
								
								if (rangeOfPoint.location != NSNotFound)
								{
									// it is a point value
									
									variable.type = [trimVariable substringToIndex:rangeOfPoint.location+1];
									variable.name = [trimVariable substringFromIndex:rangeOfPoint.location+1];
									if (nil != propertyType && [propertyType length] > 0) {
										variable.propertyType = propertyType;
									}else {
										variable.propertyType = @"nonatomic,retain";
									}

									
								}
								else 
								{
									// it is not a point value
									NSArray *temp = [trimVariable componentsSeparatedByString:@" "];
									if ([temp count]<2) {
										temp = [trimVariable componentsSeparatedByString:@"\t"];
									}
//									NSLog(@"variable is not point = %@",temp);
									variable.type = [temp objectAtIndex:0];
									variable.name = [temp lastObject];
									if (nil != propertyType && [propertyType length]>0) {
										variable.propertyType = propertyType;
										
									}else {
										variable.propertyType = @"nonatomic,assgin";
									}

								}
//								variable.hasProperty = [self isVariableHasProperty:variable.name className:className forFile:[fileReference name]];
								variable.hasProperty = [synthesizeArray containsObject:variable.name];
//								variable.hasProperty = [self existString:variable.name inArray:synthesizeArray];
								
								
								[oneVariableArray addObject:variable];
								[variable release];
							}
						}
					}
					
					XPPClassName *oneClass = [[XPPClassName alloc] initWithName:className];
					oneClass.variableNames = oneVariableArray;
					[allClasses addObject:oneClass];
					[oneClass release];
				}
			}
			return allClasses;
		}
	}
	return nil;
}



// fuction helper for subString between the stringA and stringB
// sample [sbuStringSourceString:@"1234{abc}sdf" start:@"{" end:@"}"] you will get @"abc" retun;







/*
//decrepted 可以不用
- (BOOL)existString:(NSString*)string inArray:(NSArray*)array
{
	for(NSString * item in array)
	{
		
		if ([item isKindOfClass:[NSString class]]) {
			if ([item isEqualToString:string]) {
				return YES;
			}
		}
		
	}
	return NO;
}
*/

- (void)insertString:(NSString*)string
		forClassName:(NSString*)className
   forHeaderFileName:(NSString*)fileName
	afterLinofString:(NSString*)standardLine{
	
	fileName = [fileName stringByReplacingOccurrencesOfString:@".h"
												   withString:@".m"];
	
	PBXFileReference *implementaionFileRef = [self implementationFileForFileName:fileName
															  inRootGroupContext:[self rootGroupOfContext]];
	//	NSString *sourceCode = [NSString stringWithContentsOfFile:[implementaionFileRef resolvedAbsolutePath]];
	NSTextStorage *text = [[[implementaionFileRef bookmark] fileDocumentLoadIfNeeded:YES] textStorage];
	NSString *sourceCode = [text string];
	NSArray *temp = [sourceCode componentsSeparatedByString:@"@implementation"];
	NSString *implementationString = nil;

	
	if ([temp count]>1) {
		for	(int i = 1; i < [temp count] ; i++){
			NSString *part = [[temp objectAtIndex:i] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
			if ([part hasPrefix:className]) {
				implementationString = part;
				break;
				
			}
		}
	}
	if (nil != implementationString) {
		NSRange partRange = [sourceCode rangeOfString:implementationString];
		NSRange insertRange = [sourceCode rangeOfString:standardLine
												options:NSLiteralSearch
												  range:partRange];
		if (NSNotFound != insertRange.location ) {
			if (![standardLine isEqualToString:@"\n"]) {
				insertRange = [sourceCode rangeOfString:@"\n"
												options:NSLiteralSearch
												  range:NSMakeRange(insertRange.location, [sourceCode length] - insertRange.location)];
				
			}
			if (NSNotFound != insertRange.location) {
				sourceCode = [sourceCode stringByReplacingCharactersInRange:NSMakeRange(insertRange.location +1, 0) 
																 withString:string];
				
				//		[sourceCode writeToFile:[implementaionFileRef resolvedAbsolutePath]
				//					 atomically:YES
				//					   encoding:NSUTF8StringEncoding
				//						  error:nil];
				[text replaceCharactersInRange:NSMakeRange(insertRange.location +1, 0)
									withString:string];
				
			}
		}

		
	}
}
- (void)insertSynthesizeString:(NSString*)string 
				  forClassName:(NSString*)className
			 forHeaderFileName:(NSString*)fileName{
	[self insertString:string
		  forClassName:className
	 forHeaderFileName:fileName
	  afterLinofString:@"\n"];
	
}
- (BOOL)isPropertyAlreadyReleaseInDealloc:(NSString*)propertyName
							 forClassName:(NSString*)className
							  headFileRef:(PBXFileReference*)headFileRef{
	NSString *fileName = [headFileRef name];
	fileName = [fileName stringByReplacingOccurrencesOfString:@".h"
												   withString:@".m"];
	
	PBXFileReference *implementaionFileRef = [self implementationFileForFileName:fileName
															  inRootGroupContext:[self rootGroupOfContext]];
	//	NSString *sourceCode = [NSString stringWithContentsOfFile:[implementaionFileRef resolvedAbsolutePath]];
	NSTextStorage *text = [[[implementaionFileRef bookmark] fileDocumentLoadIfNeeded:YES] textStorage];
	NSString *sourceCode = [text string];
	NSArray *temp = [sourceCode componentsSeparatedByString:@"@implementation"];
	NSString *implementationString = nil;
	
	
	if ([temp count]>1) {
		for	(int i = 1; i < [temp count] ; i++){
			NSString *part = [[temp objectAtIndex:i] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
			if ([part hasPrefix:className]) {
				implementationString = part;
				break;
				
			}
		}
	}
	if (nil != implementationString) {
		NSString *deallocPart = [implementationString subStringSourceBetweenStringStart:@"dealloc" 
																					end:@"}"];
		if (nil != deallocPart && [deallocPart length] > 0) {
			NSArray *temp = [deallocPart componentsSeparatedByString:@"\n"];
			if ([temp count] > 1) {
				NSString *comp = [NSString stringWithFormat:@"self.%@",propertyName];
				NSString *line = [self lineThatContainString:comp inArray:temp];
				if (nil != line && [line length] > 0) {
					return YES;
				}
			}
		}
		
	}

	return NO;
}
- (void)autoCompletePropertySynthesizeForVariableName:(NSString *)variableName 
										 variableType:(NSString*)variableType 
										  inClassName:(NSString *)className 
								 inSourceCodeTextView:(XCSourceCodeTextView*)sourceCodeTextView 
											  isPoint:(BOOL)isPoint{

	if (nil != variableName && [variableName length] >0 && nil != className && [className length] > 0 && nil != sourceCodeTextView) {
		NSString *propertyName = [variableName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"_"]];
		PBXFileReference *headFileRef = [sourceCodeTextView file];
		
//		NSString *headerSourceCode = [NSString stringWithContentsOfFile:[headFileRef resolvedAbsolutePath]];
		NSTextStorage *text = [[[headFileRef bookmark] fileDocumentLoadIfNeeded:YES] textStorage]; 
		
		NSString *headerSourceCode = [text string]; 

		//check the property do we have the property already write
		NSMutableArray *propertyArray = [self allPropertyForClass:className
														  forFile:headFileRef];
		NSString *propertyType = isPoint ? @"(nonatomic, retain)":@"(nonatomic, assign)";															
		NSString *lineString = [self lineThatContainString:propertyName
												   inArray:propertyArray];
		if (nil == lineString) {
			//we add line in to the source String;
			NSRange classStringRange = [self rangeOfClassName:className inFile:headFileRef];
			NSLog(@"classString = %@",[headerSourceCode substringWithRange:classStringRange]);
			NSRange insertRange = [headerSourceCode rangeOfString:@"}"
														  options:NSLiteralSearch
															range:classStringRange];
			if (NSNotFound != insertRange.location) {
				insertRange = NSMakeRange(insertRange.location +1, 0);
				NSString *propertyString = [NSString stringWithFormat:@"\n@property %@ %@\t\t\t\t%@;",propertyType,variableType,propertyName];
				if ([variableType isStringContainOtherString:@"*"]) {
					propertyString = [NSString stringWithFormat:@"\n@property %@ %@ %@;",propertyType,variableType,propertyName];
				}
				
				[text replaceCharactersInRange:insertRange
									withString:propertyString];
				
			}
			
		}else {
			propertyType = [lineString subStringSourceStringStart:@"("
															  end:@")"];
			
		}


		
		NSArray *synthesizeArray = [self allSynthesizeForClass:className
													   forFile:[headFileRef name]];
		NSString *line = [self lineThatContainString:propertyName inArray:synthesizeArray];
		if (nil == line) {
			NSString *synthesize = [propertyName isEqualToString:variableName]?variableName:[NSString stringWithFormat:@"%@ \t\t\t\t= %@",propertyName,variableName];
			
			NSString *stringForInsert = [NSString stringWithFormat:@"@synthesize %@;\n",synthesize];
			[self insertSynthesizeString:stringForInsert
							forClassName:className
					   forHeaderFileName:[headFileRef name]];
			
			
		}
		
		if ([propertyType isStringContainOtherString:@"retain"]||[propertyType isStringContainOtherString:@"copy"]) {
			//we need add self.variable = nil to dealloc;
			if (![self isPropertyAlreadyReleaseInDealloc:propertyName
											forClassName:className
											 headFileRef:headFileRef]) {
				NSString *stringForInsert = [NSString stringWithFormat:@"\n\tself.%@ = nil;",propertyName];
				[self insertString:stringForInsert
					  forClassName:className
				 forHeaderFileName:[headFileRef name]
				  afterLinofString:@"dealloc"];
				
			}
			
		}
		
		
	}
}
@end
